#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@NAME          : imgact.py
@TIME          : 2024/11/19 22:14:38
@AUTHOR        : chenlip
@VERSION       : 0.0.1
@DESCRIPTION   : 这是一个图像处理的类,用于图像的处理,如图像的去水印，裁剪,缩放,旋转，去除背景等
'''
# --------------------------引用--------------------------
import os, sys, json
from common.utils import Utils as ut
from common.minioact import minioclient
import cv2
import numpy as np
from PIL import Image
# --------------------------引用--------------------------

class ImgAct:
    def __init__(self):
        pass
    
    @staticmethod
    def cut_water(src:str, dst:str=None, mask:str=None):
        '''
            去除图像中的水印
            水印目录：
                https://minio.51epub.com/static/images/doubaoaimask.png
            :Args:
                - src: 原始图像, 例如：d:/yuan.jpg
                - mask: 水印蒙版图像, 例如：d:/di.jpg
                - dst: 去除水印后的图像路径，例如：d:/result.jpg
            :Returns:
                返回去除水印后的图像路径
        '''
        mc = minioclient()
        _mask = mask
        if mask is None: 
            _mask = os.path.join(ut.APPLICATION_ROOT, 'static', 'images', 'doubaoaimask.png')  # 黑底白字
            print(ut.cco("蒙版文件: " + _mask, "green"))
            if not os.path.exists(_mask):
                print(ut.cco("蒙版 文件不存在 !", "red"))
                # 使用mc下载文件
                mc.download_file("images/doubaoaimask.png", _mask)

        _srcspl = os.path.basename(src).split('.')
        _ext = _srcspl[-1]
        if dst is None:
            _dst = os.path.join(os.path.dirname(src), "cw-" + _srcspl[0] + '.' + _ext)
            print(ut.cco("目标文件: " + _dst, "green"))

        # # 设置环境变量以忽略 libpng 警告
        # os.environ['OPENCV_LOG_LEVEL'] = 'ERROR'

        # # 设置 OpenCV 的日志级别为错误级别，忽略警告
        # cv2.utils.logging.setLogLevel(cv2.utils.logging.LOG_LEVEL_ERROR)

        # 默认的彩色图(IMREAD_COLOR)方式读入原始图像
        srcimg = cv2.imread(src)
        if srcimg is None:
            raise FileNotFoundError(f"无法读取原始图像文件: {src}")
        # 灰度图(IMREAD_GRAYSCALE)方式读入水印蒙版图像
        maskimg = cv2.imread(_mask, cv2.IMREAD_GRAYSCALE)  
        if maskimg is None:
            raise FileNotFoundError(f"无法读取水印蒙版图像文件: {_mask}")
        # 获取图像的通道数
        num_channels = maskimg.ndim
        print(ut.cco(f"图像通道数: {num_channels}", "blue"))
        
        # 确保蒙版图像的尺寸与原始图像相同
        if srcimg.shape[:2] != maskimg.shape[:2]:
            raise ValueError("蒙版图像的尺寸与原始图像的尺寸不匹配")

        # 参数：目标修复图像; 蒙版图（定位修复区域）; 选取邻域半径; 修复算法(包括INPAINT_TELEA/INPAINT_NS， 前者算法效果较好)
        dstimg = cv2.inpaint(srcimg, maskimg, 3, cv2.INPAINT_TELEA)

        # 确保输出文件路径的扩展名为 .png
        if not _dst.lower().endswith('.png'):
            raise ValueError(f"Invalid file extension for output file: {_dst}. Expected .png")


        cv2.imwrite(_dst, dstimg)

    # cut_water
    @staticmethod
    def single_rm_wm(img_fname:str, crop_coord:list, logo_color:list) -> str:
        '''
            根据传参数,单独去水印的方式 去除某张图片的水印
            :Args:
                img_fname: 图片的全路径名字, 例如: d:/temp/t_1.jpg
                crop_coord: 裁剪的坐标, 例如: [y0, y1, x0, x1]
                logo_color: logo的颜色范围, 例如: [[200,200,200], [250,250,250]]
            :Returns:
                返回去除水印后的图片路径
        '''
        # 源图片的路径
        full_img_path = img_fname

        # logo的临时文件的路径
        _logo_temp_path = os.path.join(os.path.dirname(full_img_path), "logotemp") 
        if not os.path.exists(_logo_temp_path): os.makedirs(_logo_temp_path)
        _logo_temp_path = os.path.join(_logo_temp_path, "logo.png")

        # 去除水印后的图片的路径
        rmwm_img_path = os.path.join(os.path.dirname(full_img_path), "newimg")
        if not os.path.exists(rmwm_img_path): os.makedirs(rmwm_img_path)
        rmwm_img_path = os.path.join(rmwm_img_path, os.path.basename(full_img_path))

        # 读取图片
        img = cv2.imread(full_img_path, 1)
        hight,width,depth = img.shape[0:3]

        # 截取特定的位置, 在OCR扫描时已经确定, 也就是去除水印的位置, 
        # 裁剪坐标为[y0:y1, x0:x1], 其中(y0, x0)是左上角的坐标, (y1, x1)是右下角的坐标
        y0 = crop_coord[0]
        y1 = crop_coord[1]
        x0 = crop_coord[2]
        x1 = crop_coord[3]

        cropped = img[y0:y1, x0:x1]
        #cropped = img[int(hight*0.8):hight, int(width*0.7):width]  # 裁剪坐标为[y0:y1, x0:x1]
        cv2.imwrite(_logo_temp_path, cropped)
        imgSY = cv2.imread(_logo_temp_path,1)

        # 图片二值化处理，把[200,200,200]-[250,250,250]以外的颜色变成0
        lowerb = logo_color[0]
        upperb = logo_color[1]
        roi_hsv = cv2.cvtColor(imgSY, cv2.COLOR_BGR2HSV) #转换到HSV
        thresh = cv2.inRange(imgSY, np.array(lowerb), np.array(upperb)) #二值化, 蒙版
        cv2.imshow('image', thresh)
        cv2.waitKey(0)

        # #创建形状和尺寸的结构元素
        kernel = np.ones((3,3), np.uint8) # 卷积核

        # 扩展待修复区域
        hi_mask = cv2.dilate(thresh, kernel, iterations=3) # 膨胀
        specular = cv2.inpaint(imgSY, hi_mask, 5, flags=cv2.INPAINT_TELEA) # inpaint修复
        cv2.imwrite(_logo_temp_path, specular)

        # # 显示原图和二值化之后的图片
        # print("显示原图logo 和 二值化之后的logo 图片")
        # _new_img = cv2.imread(_logo_temp_path)
        # cv2.imshow('image', np.hstack([imgSY, _new_img]))
        # cv2.waitKey(0)

        # # 覆盖图片
        imgSY_s = Image.open(_logo_temp_path) # 读取logo临时去水印的图片
        img_s = Image.open(full_img_path) # 读取原图

        img_s.paste(imgSY_s, (x0,y0)) # PIL 的图粘贴是从左上角开始的, 所以这里的坐标是(x0, y0); 请注意cv2的坐标格式是(y0, x0)
        img_s.save(rmwm_img_path)

        print(f"原图 {full_img_path} 去水印完成, 请查看:{rmwm_img_path}, 坐标为: {crop_coord}, logo颜色范围为: {logo_color}")

        # 显示原图和去水印之后的图片
        _new_img_cv2 = cv2.imread(rmwm_img_path)
        img_cv2 = cv2.imread(full_img_path)
        # cv2.imshow('image', np.hstack([img_cv2, _new_img_cv2]))
        # cv2.waitKey(0)

        return rmwm_img_path

    # 下载图片
    @staticmethod
    def get_img_from_mc(imgurl:str, savepath:str, bucketname:str="static") -> str:
        '''
            下载图片
            :Args:
                imgurl: 图片的url地址, 例如: static/images/doubaoaimask.png
                savepath: 保存的路径
            :Returns:
                返回保存的物理路径
        '''
        mc = minioclient(bucket_name=bucketname) # 默认是bucket_name = "static"
        mc.download_file(imgurl, savepath)
        return savepath